/**
 * 轮播图BLOB存储功能测试脚本
 * 使用方法：node scripts/test-carousel-blob.js
 */

const fs = require('fs');
const path = require('path');
const axios = require('axios');
const FormData = require('form-data');
const { promisify } = require('util');
const readFileAsync = promisify(fs.readFile);

// 配置
const API_BASE_URL = 'http://localhost:3000/api';
const TEST_IMAGE_PATH = path.join(__dirname, '../test-assets/test-banner.jpg');
const ADMIN_TOKEN = ''; // 填入管理员Token

// 测试状态
let createdCarouselId = null;

// 测试过程中的延迟函数
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

// 颜色输出
const colors = {
  reset: '\x1b[0m',
  bright: '\x1b[1m',
  green: '\x1b[32m',
  red: '\x1b[31m',
  yellow: '\x1b[33m',
  blue: '\x1b[34m',
  cyan: '\x1b[36m'
};

// 日志函数
const log = {
  info: (msg) => console.log(`${colors.cyan}[INFO]${colors.reset} ${msg}`),
  success: (msg) => console.log(`${colors.green}[SUCCESS]${colors.reset} ${msg}`),
  error: (msg) => console.log(`${colors.red}[ERROR]${colors.reset} ${msg}`),
  warn: (msg) => console.log(`${colors.yellow}[WARN]${colors.reset} ${msg}`),
  title: (msg) => console.log(`\n${colors.bright}${colors.blue}=== ${msg} ===${colors.reset}\n`)
};

// 1. 测试获取轮播图列表
async function testGetCarousels() {
  log.title('测试获取轮播图列表');
  
  try {
    const response = await axios.get(`${API_BASE_URL}/carousels`);
    log.info(`获取到 ${response.data.data.length} 个轮播图`);
    
    if (response.data.data.length > 0) {
      log.info(`第一个轮播图: ID=${response.data.data[0].id}, 标题=${response.data.data[0].title || '无标题'}`);
    }
    
    log.success('获取轮播图列表成功');
    return response.data.data;
  } catch (error) {
    log.error(`获取轮播图列表失败: ${error.message}`);
    if (error.response) {
      log.error(`服务器响应: ${JSON.stringify(error.response.data)}`);
    }
    throw error;
  }
}

// 2. 测试创建轮播图 (BLOB)
async function testCreateCarouselWithBlob() {
  log.title('测试创建轮播图 (BLOB存储)');
  
  if (!fs.existsSync(TEST_IMAGE_PATH)) {
    log.error(`测试图片不存在: ${TEST_IMAGE_PATH}`);
    log.warn('请确保test-assets目录存在，并包含test-banner.jpg文件');
    
    // 创建目录和测试图片的示例代码
    log.info('创建测试目录和测试图片...');
    const testAssetsDir = path.join(__dirname, '../test-assets');
    if (!fs.existsSync(testAssetsDir)) {
      fs.mkdirSync(testAssetsDir, { recursive: true });
    }
    
    // 从网络下载测试图片
    try {
      log.info('从网络获取测试图片...');
      const imageResponse = await axios.get(
        'https://picsum.photos/800/400',
        { responseType: 'arraybuffer' }
      );
      fs.writeFileSync(TEST_IMAGE_PATH, Buffer.from(imageResponse.data));
      log.success(`测试图片已创建: ${TEST_IMAGE_PATH}`);
    } catch (error) {
      log.error(`无法获取测试图片: ${error.message}`);
      throw error;
    }
  }
  
  try {
    // 读取测试图片
    const imageBuffer = await readFileAsync(TEST_IMAGE_PATH);
    
    // 创建FormData
    const formData = new FormData();
    formData.append('image', imageBuffer, {
      filename: 'test-banner.jpg',
      contentType: 'image/jpeg'
    });
    formData.append('title', '测试轮播图 ' + new Date().toLocaleTimeString());
    formData.append('sort_order', '99');
    
    // 发送请求
    const response = await axios.post(
      `${API_BASE_URL}/carousels`,
      formData,
      {
        headers: {
          ...formData.getHeaders(),
          'Authorization': `Bearer ${ADMIN_TOKEN}`
        }
      }
    );
    
    createdCarouselId = response.data.data.id;
    log.info(`创建的轮播图ID: ${createdCarouselId}`);
    log.info(`轮播图访问URL: ${response.data.data.image_url}`);
    log.success('创建轮播图成功');
    return response.data;
  } catch (error) {
    log.error(`创建轮播图失败: ${error.message}`);
    if (error.response) {
      log.error(`服务器响应: ${JSON.stringify(error.response.data)}`);
    }
    throw error;
  }
}

// 3. 测试获取轮播图详情
async function testGetCarouselDetail(id) {
  const carouselId = id || createdCarouselId;
  log.title(`测试获取轮播图详情 (ID=${carouselId})`);
  
  if (!carouselId) {
    log.warn('没有指定轮播图ID，跳过测试');
    return null;
  }
  
  try {
    const response = await axios.get(`${API_BASE_URL}/carousels/${carouselId}`);
    log.info(`轮播图标题: ${response.data.data.title || '无标题'}`);
    log.info(`图片URL: ${response.data.data.image_url}`);
    log.info(`MIME类型: ${response.data.data.mime_type}`);
    log.info(`文件名: ${response.data.data.file_name}`);
    log.info(`文件大小: ${response.data.data.file_size} 字节`);
    log.success('获取轮播图详情成功');
    return response.data.data;
  } catch (error) {
    log.error(`获取轮播图详情失败: ${error.message}`);
    if (error.response) {
      log.error(`服务器响应: ${JSON.stringify(error.response.data)}`);
    }
    throw error;
  }
}

// 4. 测试获取轮播图图片
async function testGetCarouselImage(id) {
  const carouselId = id || createdCarouselId;
  log.title(`测试获取轮播图图片 (ID=${carouselId})`);
  
  if (!carouselId) {
    log.warn('没有指定轮播图ID，跳过测试');
    return null;
  }
  
  try {
    const response = await axios.get(
      `${API_BASE_URL}/carousels/${carouselId}/image`,
      { responseType: 'arraybuffer' }
    );
    
    const contentType = response.headers['content-type'];
    const contentDisposition = response.headers['content-disposition'];
    const imageSize = response.data.length;
    
    log.info(`图片MIME类型: ${contentType}`);
    log.info(`Content-Disposition: ${contentDisposition || '未设置'}`);
    log.info(`图片大小: ${imageSize} 字节`);
    
    // 保存图片到本地用于验证
    const outputPath = path.join(__dirname, `../test-assets/downloaded-carousel-${carouselId}.jpg`);
    fs.writeFileSync(outputPath, Buffer.from(response.data));
    log.info(`图片已保存到: ${outputPath}`);
    
    log.success('获取轮播图图片成功');
    return {
      contentType,
      contentDisposition,
      imageSize,
      outputPath
    };
  } catch (error) {
    log.error(`获取轮播图图片失败: ${error.message}`);
    if (error.response) {
      log.error(`服务器响应状态码: ${error.response.status}`);
    }
    throw error;
  }
}

// 5. 测试更新轮播图
async function testUpdateCarousel(id) {
  const carouselId = id || createdCarouselId;
  log.title(`测试更新轮播图 (ID=${carouselId})`);
  
  if (!carouselId) {
    log.warn('没有指定轮播图ID，跳过测试');
    return null;
  }
  
  try {
    const response = await axios.put(
      `${API_BASE_URL}/carousels/${carouselId}`,
      {
        title: '已更新的轮播图 ' + new Date().toLocaleTimeString(),
        sort_order: 88
      },
      {
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${ADMIN_TOKEN}`
        }
      }
    );
    
    log.info(`更新结果: ${response.data.message}`);
    log.success('更新轮播图成功');
    return response.data;
  } catch (error) {
    log.error(`更新轮播图失败: ${error.message}`);
    if (error.response) {
      log.error(`服务器响应: ${JSON.stringify(error.response.data)}`);
    }
    throw error;
  }
}

// 6. 测试删除轮播图
async function testDeleteCarousel(id) {
  const carouselId = id || createdCarouselId;
  log.title(`测试删除轮播图 (ID=${carouselId})`);
  
  if (!carouselId) {
    log.warn('没有指定轮播图ID，跳过测试');
    return null;
  }
  
  try {
    const response = await axios.delete(
      `${API_BASE_URL}/carousels/${carouselId}`,
      {
        headers: {
          'Authorization': `Bearer ${ADMIN_TOKEN}`
        }
      }
    );
    
    log.info(`删除结果: ${response.data.message}`);
    log.success('删除轮播图成功');
    return response.data;
  } catch (error) {
    log.error(`删除轮播图失败: ${error.message}`);
    if (error.response) {
      log.error(`服务器响应: ${JSON.stringify(error.response.data)}`);
    }
    throw error;
  }
}

// 主测试函数
async function runTests() {
  log.title('开始轮播图BLOB存储功能测试');
  
  if (!ADMIN_TOKEN) {
    log.warn('管理员Token未设置，部分测试将失败');
    log.info('请在脚本顶部设置ADMIN_TOKEN变量');
  }
  
  try {
    // 执行测试
    await testGetCarousels();
    
    // 如果管理员Token已设置，执行需要权限的测试
    if (ADMIN_TOKEN) {
      await testCreateCarouselWithBlob();
      await delay(1000); // 短暂延迟确保数据库更新
      
      await testGetCarouselDetail();
      await testGetCarouselImage();
      await testUpdateCarousel();
      
      await delay(1000); // 短暂延迟确保数据库更新
      await testGetCarouselDetail(); // 再次获取详情验证更新
      
      // 询问是否删除
      console.log('\n');
      log.warn('轮播图测试完成，但尚未删除创建的测试数据');
      log.warn(`如需删除测试数据(ID=${createdCarouselId})，请取消注释脚本末尾的测试删除行`);
      
      // 删除测试数据 (默认注释，如需删除请取消注释)
      // await testDeleteCarousel();
    }
    
    log.title('轮播图BLOB存储功能测试完成');
  } catch (error) {
    log.title('测试过程中出现错误');
    process.exit(1);
  }
}

// 执行测试
runTests(); 